/* Copyright (C) 2022 ulandlink. All rights reserved.
 *
 * File Name:				app_rn8302b_drv.c
 *
 *File Description:			
 *
 * File History:            2022-5-26   first version    zenglj@ulandlink.com
 *
 */
#include "app_rn8302b_drv.h"
#include "math.h"
#include <main.h>
#include <rtthread.h>
#include <drv_uart.h>
#include <pin.h>
#include <drv_gpio.h>
#include <rtdevice.h>
#include <app_charge_drv.h>
//#include <app_meter_param.h>
 
#define LOG_TAG                    "meter.drv"
#define LOG_LVL                    LOG_LVL_INFO
#include "ulog.h"

/**********LOCAL TYPE, CONSTANT, MACRO DEFINITIONS SECTION******/

#if defined(EVC30_EU)
#define u8 unsigned char

/***************��������*********************/
#define METER_POWER_OUT()		rt_pin_mode(GET_PIN(B,1), PIN_MODE_OUTPUT)
#define METER_POWER_ON()  		rt_pin_write(GET_PIN(B,1), FALSE) //使能SPI
#define METER_POWER_OFF()  		rt_pin_write(GET_PIN(B,1), TRUE)

//#define METER_RST_OUT()			rt_pin_mode(GET_PIN(E,8), PIN_MODE_OUTPUT)
//#define METER_RST_HIGH()  		rt_pin_write(GET_PIN(E,8), TRUE) //使能SPI
//#define METER_RST_LOW()  		rt_pin_write(GET_PIN(E,8), FALSE)

//#define METER_INTN_OUT()			rt_pin_mode(GET_PIN(E,7), PIN_MODE_OUTPUT)
//#define METER_TNTN_ON()  		    rt_pin_write(GET_PIN(E,7), TRUE) //使能SPI
//#define METER_TNTN_OFF()  		rt_pin_write(GET_PIN(E,7), FALSE)

#define METER_CS_OUT()			rt_pin_mode(GET_PIN(B,10), PIN_MODE_OUTPUT)
#define METER_CS_ON()  		    rt_pin_write(GET_PIN(B,10), FALSE) //使能SPI
#define METER_CS_OFF()  		    rt_pin_write(GET_PIN(B,10), TRUE)

#define METER_SCK_OUT()   	    rt_pin_mode(GET_PIN(E,15), PIN_MODE_OUTPUT)
#define METER_SCK_HIGH()       	rt_pin_write(GET_PIN(E,15), TRUE)
#define METER_SCK_LOW()       	rt_pin_write(GET_PIN(E,15), FALSE)

#define METER_MISO_IN()  	        rt_pin_mode(GET_PIN(A,6), PIN_MODE_INPUT_PULLUP)  //设为上拉输入
#define METER_MISO_READ()     	rt_pin_read(GET_PIN(A,6))           

#define METER_MOSI_OUT()  	    rt_pin_mode(GET_PIN(G, 10), PIN_MODE_OUTPUT)
#define METER_MOSI_HIGH()     	rt_pin_write(GET_PIN(G, 10), TRUE)
#define METER_MOSI_LOW()     	    rt_pin_write(GET_PIN(G, 10), FALSE)


/*************�Ĵ�����ַ**************/
/******�����Ĵ���*******/
#define UA          0x0007
#define UB          0x0008
#define UC          0x0009

#define IA          0x000B
#define IB          0x000C
#define IC          0x000D
#define IN          0x000E

#define PA          0x0014
#define PB          0x0015
#define PC          0x0016
#define PT          0x0017
#define QA          0x0018
#define QB          0x0019
#define QC          0x001A
#define QT          0x001B

#define PEA         0x0030
#define PEB         0x0031
#define PEC         0x0032
#define PET         0x0033

#define FRQ         0x057
/*****���üĴ���******/
#define	HFCONST1	0x0100
#define	HFCONST2	0x0101
#define	IStart_PS	0x0102
#define	ZXOT		0x0105
#define	PRTH1L		0x0106
#define	PRTH1H		0x0107
#define	PRTH2L		0x0108
#define	PRTH2H		0x0109
#define	PHSUA		0x010C
#define	PHSUB		0x010D
#define	PHSUC		0x010E
#define	PHSIA		0x010F
#define	PHSIB		0x0110
#define	PHSIC		0x0111
#define	GSUA		0x0113
#define	GSUB		0x0114
#define	GSUC		0x0115
#define	GSIA		0x0116
#define	GSIB		0x0117
#define	GSIC		0x0118
#define	GSIN		0x0119
#define	GPA			0x0128
#define	GPB			0x0129
#define GPC			0x012A
#define	GQA			0x012B
#define	GQB			0x012C
#define	GQC			0x012D
#define	GSA			0x012E
#define	GSB			0x012F
#define	GSC			0x0130
#define	PA_PHSL		0x0131
#define	PB_PHSL		0x0132
#define	PC_PHSL		0x0133
#define	QA_PHSL		0x0134
#define	QB_PHSL		0x0135
#define	QC_PHSL		0x0136

#define	CFCFG		0x0160
#define EMUCFG      0x0161
#define EMUCON      0x0162
#define WSAVECON    0x0163
#define	PQSign		0x0166
#define	CheckSum1	0x016A 

#define WREN        0x0180 /*дʹ��*/
#define	WMSW		0x0181 /*����ģʽ�л�*/
#define SOFTRST     0x0182
#define ADCCFG      0x0183

#define MODSEL      0X0186

#define SYSSR       0x018a
#define RData       0x018c
#define WData       0x018d
#define	DeviceID	0x018f

#define Un 220 //У����׼Դ��ѹ
//#define Un 233 //У����׼Դ��ѹ
#define In 2.17//У����׼Դ����
#define EC 3200 //�������
#define Fosc 8.192 //����Ƶ��
#define fosc 8192000
#define std_voltage_value 43800000.0 //У����ѹ�Ĵ�����׼ֵ ʵ�ʱ�׼ֵ��mA��*200
#define std_current_value 10900000.0 //У�������Ĵ�����׼ֵ
//#define std_current_value 38687500.0 //У�������Ĵ�����׼ֵ ʵ�ʱ�׼ֵ��mA��*1250
//#define std_current_value 31000000.0 //У�������Ĵ�����׼ֵ ʵ�ʱ�׼ֵ��mA��*1250
//#define std_power_value  9105682.0//У�����ʼĴ�����׼ֵ
#define std_power_value  162601470.0//У�����ʼĴ�����׼ֵ


#define DEFAULT_HFCONST 0x0c94
#define DEFAULT_GSIX     0xcbad
#define DEFAULT_GSUX     0xcd68
#define DEFAULT_QX_PHSL  0XAA
#define DEFAULT_PX_PHSL  0XAA

#define VRMS_FARC 2000
//#define IRMS_FARC 12500
#define IRMS_FARC 10000
#define POWER_FARC 238

typedef union
{
	uint8_t ucTempBuf[8];
	uint32_t lTemp32;
	uint16_t wTemp16;
	uint8_t ucTemp8;
}StructDataComm_TypeDef;

//StructDataComm_TypeDef RN8302DataComm;

typedef struct
{
	int32 Vrms_a;//A���ѹ��Чֵ
	int32 Vrms_b;//B���ѹ��Чֵ
	int32 Vrms_c;//C���ѹ��Чֵ
	
	int32 Irms_a;//A�������Чֵ
	int32 Irms_b;//B�������Чֵ
	int32 Irms_c;//C�������Чֵ
	int32 Irms_n;//���ߵ�����Чֵ
	
	int32 Ppwr_a;//A���й�����
	int32 Ppwr_b;//B���й�����
	int32 Ppwr_c;//C���й�����
	int32 Ppwr_total;//�����й�����
	int32 Qpwr_total;
	
	int32 Epa_a_now;//��ǰA���й�����
	int32 Epa_b_now;//��ǰB���й�����
	int32 Epa_c_now;//��ǰC���й�����
	int32 Epa_total_now;//��ǰ�����й�����
	
	int32 Epa_a_begin;//��ʼ��A���й�����
	int32 Epa_b_begin;//��ʼ��B���й�����
	int32 Epa_c_begin;//��ʼ��C���й�����
	int32 Epa_total_begin;//��ʼ�������й�����
	
	int32 freq;//Ƶ��
	
	BOOL first_power_flag;//�ϵ��־λ
	
}meter_info_t;

static meter_info_t meter_info = {0};
static struct_rn8302_init_para rn8302b_calibrate_para;
static phase_type_e device_phase_type = ERROR_PHASE;

static struct_rn8302_init_para rn8302_init_para_default =
{
	.para_HFconst = DEFAULT_HFCONST,
	.para_GSUA = DEFAULT_GSUX,//ͨ������
	.para_GSUB = DEFAULT_GSUX,
	.para_GSUC = DEFAULT_GSUX,
	.para_GSIA = DEFAULT_GSIX,
	.para_GSIB = DEFAULT_GSIX,
	.para_GSIC = DEFAULT_GSIX,
	.para_GSIN = DEFAULT_GSIX,

	.para_PA_PHSL = DEFAULT_PX_PHSL,
	.para_PB_PHSL = DEFAULT_PX_PHSL,
	.para_PC_PHSL = DEFAULT_PX_PHSL,
	.para_QA_PHSL = DEFAULT_QX_PHSL,
	.para_QB_PHSL = DEFAULT_QX_PHSL,
	.para_QC_PHSL = DEFAULT_QX_PHSL,

}; 


uint8_t meter_fault;

static void delay_us(uint32_t value)
{
    uint32_t i=0;
    for(i=0;i<(value*200);i++)
    {
    }
}

//------------------��һ������оƬ������spiЭ��
static void meter_spi_init(void)
{
	METER_POWER_OUT();
	METER_POWER_ON();
	//���ܼ���оƬ0����spi��ʼ��
	METER_CS_OUT();    //片选�?�为输�??
	METER_CS_OFF();

	//METER_RST_OUT();

	METER_SCK_OUT();  //时钟设为输出
	METER_SCK_LOW();  //时钟输出�?
	
	METER_MISO_IN();  //主机输入，从机输�?

	METER_MOSI_OUT(); //主机输出，从机输�?
	METER_MOSI_LOW();
}

static void meter_spi_wr_byte(uint8_t byte)
{
	uint8_t i;
	
	//rt_enter_critical();
	for(i=0; i<8; i++)
	{
		METER_SCK_HIGH();
		delay_us(2);
		if(byte&0x80)
		{
			METER_MOSI_HIGH();
		}
		else
		{
			METER_MOSI_LOW();
		}
		delay_us(2);
		METER_SCK_LOW();	
		delay_us(2);
		byte <<= 1;
	}
	
	METER_MOSI_HIGH();
	delay_us(4);
	//rt_exit_critical();
}

static uint8_t meter_spi_rd_byte(void)
{
	uint8_t i, byte=0;
	
	//rt_enter_critical();
	for(i=0; i<8; i++)
	{
		byte <<= 1;
		METER_SCK_HIGH();
		delay_us(2);
		METER_SCK_LOW();
		delay_us(2);
		if(METER_MISO_READ())
			byte = byte + 0x01;
		delay_us(2);
	}
	//rt_exit_critical();
	return byte;
}

static BOOL meter_spi_write(uint16_t wReg, uint8_t *pBuf, uint8_t DatLen)
{
	uint8_t i, temp, chksum, repeat;
	BOOL err = TRUE;
	
	if((DatLen == 0) || (DatLen > 4))
		return FALSE;
	for(repeat = 3; repeat != 0; repeat--)
	{
		METER_CS_OFF();
		delay_us(1);
		METER_CS_ON();
		delay_us(1);
		temp = (uint8_t)(wReg & 0x00ff);
		chksum = temp;
		meter_spi_wr_byte(temp);
		temp = (((uint8_t)(wReg >> 4)) & 0xf0)+ 0x80;
		chksum += temp;
		meter_spi_wr_byte(temp);
		log_d(" write reg 0x%x.", wReg);
		delay_us(2);
		for(i = DatLen; i > 0; i--)
		{
			meter_spi_wr_byte(pBuf[i-1]);
			log_d(" write buf[%d]:0x%x", (i-1), pBuf[i-1]);
			chksum += pBuf[i-1];
			delay_us(2);
		}
		chksum = ~chksum;
		meter_spi_wr_byte(chksum);
		//LOG_E("write checksum:%d.",chksum);
		
		meter_spi_wr_byte(0x8D);//У��
		chksum = 0x8D;
		temp = 0x10;
		meter_spi_wr_byte(temp);
		chksum += temp;
		delay_us(2);
		for(i=3; i>0; i--)
		{
			temp = meter_spi_rd_byte();
			if(DatLen >= i)
			{
				if(temp != pBuf[i - 1])
				{
					err = FALSE;
					log_e(" spi write check failed.");
					break;
				}
			}
			chksum += temp;
		}
		if(err == TRUE)
		{
			chksum = ~chksum;
			temp = meter_spi_rd_byte();
			if(temp != chksum){
				log_e(" spi write checksum failed.");
				err = FALSE;
			}
		}
		METER_CS_OFF();
		if(err == TRUE)
			break;
			
	}
	delay_us(2);
	METER_SCK_HIGH();
	METER_MOSI_HIGH();
	return err;
	
}

static BOOL meter_spi_read(uint16_t wReg, uint8_t *pBuf, uint8_t DatLen)
{
	uint8_t i, temp, chksum, repeat, chksum_read;
	uint32_t buffer_u32;
	uint8_t buffer_u8;
	BOOL err  = TRUE;
	if(DatLen == 0)
		return FALSE;
	for(repeat=3; repeat!=0; repeat--)
	{
		METER_CS_OFF();
		delay_us(1);
		METER_CS_ON();
		delay_us(2);
		temp = (uint8_t)(wReg & 0x00ff);
		chksum = temp;
		meter_spi_wr_byte(temp);
		temp = (((uint8_t)(wReg >> 4)) & 0xf0);
		chksum += temp;
		meter_spi_wr_byte(temp);
		log_d("read reg 0x%x.", wReg);
		
		for(i=DatLen; i>0; i--)
		{
			pBuf[i-1] = meter_spi_rd_byte();
			log_d("read buf[%d] = 0x%x.", (i-1), pBuf[i-1]);
			chksum += pBuf[i-1];
		}
		chksum = ~chksum;
		chksum_read = meter_spi_rd_byte();
		//log_d("read chksum : 0x%x cal chkcum : 0x%x", chksum_read, chksum);
		if(chksum_read != chksum){
			log_d(" pBuf1 = %d pBuf2 = %d pBuf3 = %d chksum = %d",pBuf[0],pBuf[1],pBuf[2],chksum);
			err = FALSE;
		}
		if(DatLen == 3){
			pBuf[3] = 0x00;
		}
		
		if(err == TRUE)
			break;

		/*
		meter_spi_wr_byte(0x8c);
		chksum = 0x8c;
		temp =  ( (uint8_t)(0x018C >> 4) & 0xf0);	
		meter_spi_wr_byte(temp);
		chksum += temp;
		for(i=4; i>0; i--)
		{
			temp = meter_spi_rd_byte();
			if(DatLen >= i)
			{
				if(temp != pBuf[i-1])
				{
					err = FALSE;
					break;
				}
			}
			chksum += temp;
		}
		if(err == TRUE)
		{
			chksum = ~chksum;
			temp = meter_spi_rd_byte();
			if(temp != chksum)
				err = TRUE;
		}
		
		METER_CS_OFF();
		if(err == TRUE)
			break;
		delay_us(4);
		*/
	}
	METER_CS_OFF();
	METER_SCK_HIGH();
	METER_MOSI_HIGH();
	
	return err;
}

//--------------
void rn8302_init(void)
{
	StructDataComm_TypeDef RN8302DataComm;
	//��ȡ����оƬУ׼����
	//app_meter_param_get(&rn8302_init_para, sizeof(rn8302_init_para[0]));
	struct_rn8302_init_para* rn8302_init_para = &rn8302_init_para_default;

	RN8302DataComm.ucTemp8 = 0xe5; // дʹ��λ
	meter_spi_write(WREN, RN8302DataComm.ucTempBuf, 1);
	
	RN8302DataComm.ucTemp8 = 0xA2; // �л���EMMģʽ
	meter_spi_write(WMSW, RN8302DataComm.ucTempBuf, 1);
	
	RN8302DataComm.ucTemp8 = 0xfa; // ������λ
	meter_spi_write(SOFTRST, RN8302DataComm.ucTempBuf, 1);
	rt_thread_mdelay(20);
	RN8302DataComm.ucTemp8 = 0xe5; // дʹ��λ
	meter_spi_write(WREN, RN8302DataComm.ucTempBuf, 1);
	
	meter_spi_write(HFCONST1, (u8 *)&rn8302_init_para->para_HFconst, 2);
	
	// ��ѹ�����ʼ��
	meter_spi_write(GSUA, (u8 *)&rn8302_init_para->para_GSUA, 2);
	meter_spi_write(GSUB, (u8 *)&rn8302_init_para->para_GSUB, 2);
	meter_spi_write(GSUC, (u8 *)&rn8302_init_para->para_GSUC, 2);
	
	// ���������ʼ��
	meter_spi_write(GSIA, (u8 *)&rn8302_init_para->para_GSIA, 2);
	meter_spi_write(GSIB, (u8 *)&rn8302_init_para->para_GSIB, 2);
	meter_spi_write(GSIC, (u8 *)&rn8302_init_para->para_GSIC, 2);
	meter_spi_write(GSIN, (u8 *)&rn8302_init_para->para_GSIN, 2);

	// �й���λ��ʼ��
	meter_spi_write(PA_PHSL, (u8 *)&rn8302_init_para->para_PA_PHSL, 2);
	meter_spi_write(PB_PHSL, (u8 *)&rn8302_init_para->para_PB_PHSL, 2);
	meter_spi_write(PC_PHSL, (u8 *)&rn8302_init_para->para_PC_PHSL, 2);

	// �޹���λ��ʼ��
	meter_spi_write(QA_PHSL, (u8 *)&rn8302_init_para->para_QA_PHSL, 2);
	meter_spi_write(QB_PHSL, (u8 *)&rn8302_init_para->para_QB_PHSL, 2);
	meter_spi_write(QC_PHSL, (u8 *)&rn8302_init_para->para_QC_PHSL, 2);

	
	RN8302DataComm.ucTempBuf[0] = 0x10; 
	RN8302DataComm.ucTempBuf[1] = 0x32;
	RN8302DataComm.ucTempBuf[2] = 0x07;
	meter_spi_write(CFCFG,RN8302DataComm.ucTempBuf,3);//��������CF������;

	RN8302DataComm.ucTempBuf[2] = 0x4C; //������Ԫ���üĴ���
	RN8302DataComm.ucTempBuf[1] = 0x00; //�����;���ֵ�ۼ� �����Ĵ����ۼ��� ����ʸ���Ͱ������ߵ���
	RN8302DataComm.ucTempBuf[0] = 0x00;
	meter_spi_write(EMUCFG,RN8302DataComm.ucTempBuf,3);

	RN8302DataComm.ucTempBuf[0] = 0x77; //��������λ
	RN8302DataComm.ucTempBuf[1] = 0x77; //��Ҫ����ʵ������������
	RN8302DataComm.ucTempBuf[2] = 0x77;
	meter_spi_write(EMUCON,RN8302DataComm.ucTempBuf,3);

	RN8302DataComm.wTemp16 = 0x5555;//����ADCͨ��������Ϊ1
	meter_spi_write(ADCCFG, RN8302DataComm.ucTempBuf, 2);	
	
	RN8302DataComm.ucTemp8 = 0x10; //��ղ������ݻ�����
	meter_spi_write(WSAVECON,RN8302DataComm.ucTempBuf,1);
	
	RN8302DataComm.ucTemp8 = 0xDC; //д����
	meter_spi_write(WREN,RN8302DataComm.ucTempBuf,1);

}

static void meter_data_read(meter_info_t* meter_info_f)
{
	meter_info_t temp_meter;
	meter_spi_read(IA, (u8 *)&temp_meter.Irms_a, 4);//ʵ�ʵ���ֵΪtemp_meter.Irms_a/5000000
	meter_info_f->Irms_a =  temp_meter.Irms_a/IRMS_FARC;//ʵ��ֵ��100��
	meter_spi_read(UA, (u8 *)&temp_meter.Vrms_a, 4);//ʵ�ʵ�ѹֵΪtemp_meter.Vrms_a/200000
	meter_info_f->Vrms_a =  temp_meter.Vrms_a/VRMS_FARC;//ʵ��ֵ��100��
	if(device_phase_type == THREE_PHASE){
		meter_spi_read(IB, (u8 *)&temp_meter.Irms_b, 4);
		meter_info_f->Irms_b =  temp_meter.Irms_b/IRMS_FARC;//ʵ��ֵ��100��
		meter_spi_read(IC, (u8 *)&temp_meter.Irms_c, 4);
		meter_info_f->Irms_c =  temp_meter.Irms_c/IRMS_FARC;//ʵ��ֵ��100��

		meter_spi_read(UB, (u8 *)&temp_meter.Vrms_b, 4);
		meter_info_f->Vrms_b =  temp_meter.Vrms_b/VRMS_FARC;//ʵ��ֵ��100��
		meter_spi_read(UC, (u8 *)&temp_meter.Vrms_c, 4);
		meter_info_f->Vrms_c =  temp_meter.Vrms_c/VRMS_FARC;//ʵ��ֵ��100��
	}
	meter_spi_read(IN, (u8 *)&temp_meter.Irms_n, 4);

	//meter_spi_read(FRQ, (u8 *)&temp_meter.freq, 3);

	meter_spi_read(PA, (u8 *)&temp_meter.Ppwr_a, 4);//ʵ���й�Ϊtemp_meter.Ppwr_a/119200
	log_d("power a value :%d", temp_meter.Ppwr_a);
	meter_spi_read(PB, (u8 *)&temp_meter.Ppwr_b, 4);
	log_d("power b value :%d", temp_meter.Ppwr_b);
	meter_spi_read(PC, (u8 *)&temp_meter.Ppwr_c, 4);
	log_d("power c value :%d", temp_meter.Ppwr_c);
	meter_spi_read(PT, (u8 *)&temp_meter.Ppwr_total, 4);
	log_d("power total value :%d", temp_meter.Ppwr_total);

	meter_spi_read(QT, (u8 *)&temp_meter.Qpwr_total, 4);
	log_d("Q power total value :%d", meter_info_f->Qpwr_total);
	//meter_spi_read(PEA, (u8 *)&temp_meter.Epa_a_now, 3);//ʵ�ʵ���Ϊtemp_meter.Epa_a_now/EC
	//meter_spi_read(PEB, (u8 *)&temp_meter.Epa_b_now, 3);
	//meter_spi_read(PEC, (u8 *)&temp_meter.Epa_c_now, 3);
	//meter_spi_read(FRQ, (u8 *)&temp_meter.freq, 3);
	//meter_spi_read(FRQ, (u8 *)&temp_meter.freq, 3);
	//meter_spi_read(FRQ, (u8 *)&temp_meter.freq, 3);

	meter_spi_read(FRQ, (u8 *)&temp_meter.freq, 3);
	
	meter_spi_read(PET, (u8 *)&temp_meter.Epa_total_now, 3);
	log_d("energy total value :%d", temp_meter.Epa_total_now);
	//meter_info_f->Irms_a =  temp_meter.Irms_a/IRMS_FARC;//ʵ��ֵ��100��
	//log_d("current a value :%d", meter_info_f->Irms_a);
	//meter_info_f->Irms_b =  temp_meter.Irms_b/IRMS_FARC;//ʵ��ֵ��100��
	//log_d("current a value :%d", meter_info_f->Irms_b);
	//meter_info_f->Irms_c =  temp_meter.Irms_c/IRMS_FARC;//ʵ��ֵ��100��
	//log_d("current a value :%d", meter_info_f->Irms_c);


	//meter_info_f->Vrms_a =  temp_meter.Vrms_a/VRMS_FARC;//ʵ��ֵ��100��
	//log_d("voltage a value :%d", meter_info_f->Vrms_a);
	//meter_info_f->Vrms_b =  temp_meter.Vrms_b/VRMS_FARC;//ʵ��ֵ��100��
	//log_d("voltage b value :%d", meter_info_f->Vrms_b);
	//meter_info_f->Vrms_c =  temp_meter.Vrms_c/VRMS_FARC;//ʵ��ֵ��100��
	//log_d("voltage c value :%d", meter_info_f->Vrms_c);

	//meter_info_f->Ppwr_a =  abs(temp_meter.Ppwr_a/1192*4);//ʵ��ֵ��100��
	//log_d("power a value :%d", meter_info_f->Ppwr_a);
	//meter_info_f->Ppwr_b =  abs(temp_meter.Ppwr_b/1192*4);//ʵ��ֵ��100��
	//log_d("power b value :%d", meter_info_f->Ppwr_b);
	//meter_info_f->Ppwr_c =  abs(temp_meter.Ppwr_c/1192*4);//ʵ��ֵ��100��
	//log_d("power c value :%d", meter_info_f->Ppwr_c);

	meter_info_f->Ppwr_total =  abs(temp_meter.Ppwr_total)/POWER_FARC/100;//ʵ��ֵ��100��


	//meter_info_f->Ppwr_total =  abs(temp_meter.Ppwr_total)/POWER_FARC;//ʵ��ֵ��100��
	//log_d("power total value :%d", meter_info_f->Ppwr_total);
	
	meter_info_f->freq = (fosc*80/temp_meter.freq/10);
	//meter_info_f->freq = 500;
	//meter_info_f->Epa_a_now =  temp_meter.Epa_a_now*10/32;//ʵ��ֵ��100��
	//meter_info_f->Epa_a_now =  temp_meter.Epa_a_now*10/32;//ʵ��ֵ��100��
	//meter_info_f->Epa_a_now =  temp_meter.Epa_a_now*10/32;//ʵ��ֵ��100��
	//log_d("energy total value :%d", meter_info_f->Epa_total_now);
	meter_info_f->Epa_total_now =  temp_meter.Epa_total_now*10/32;//ʵ��ֵ��100��
	//log_d("energy total value :%d", meter_info_f->Epa_total_now);
	//log_d("freq value :%dhz", meter_info_f->freq);
}
/**********************************************************
//����У��
//У������ ����� 220V 1.5A �趨�������ECΪ3200
//��220V���� ��ѹ�Ĵ���ֵ��׼Ϊ44000000 1.5A���� �����Ĵ���ֵ��׼Ϊ7500000 
//PF = 1 ʱ���й�����Ϊ330W �й��Ĵ���ֵ��׼Ϊ39339066
//PF = 0.5 ʱ�� �й�����Ϊ115W���й��Ĵ���ֵ��׼Ϊ19669533
//HFConst = 3E73H
//У������ 
//1����������
//2��ͨ������У�� 220V���� ADC����˵�ѹΪ220mVʱ 1.5A�������� ADC�˵�ѹΪ50mV
//���������ѹ�������Ĵ�����ֵ
************************************************************/

//У��ǰ���ó�ʼ��
void meter_calibrate_init(void)
{
	StructDataComm_TypeDef RN8302DataComm;
	uint32_t zore = 0x0000;

	RN8302DataComm.ucTemp8 = 0xe5; // дʹ��λ
	meter_spi_write(WREN, RN8302DataComm.ucTempBuf, 1);

	//1��ADC����ѡ��
	RN8302DataComm.wTemp16 = 0x0555;//����ADCͨ����Ϊ1
	meter_spi_write(0x0183, RN8302DataComm.ucTempBuf, 2);

	//2��HFConst����
	RN8302DataComm.wTemp16 = DEFAULT_HFCONST;//��Ƶ���峣����ʼ��

	meter_spi_write(HFCONST1, RN8302DataComm.ucTempBuf, 2);
	//3�������Ĵ���
	RN8302DataComm.ucTempBuf[2] = 0x4C; //������Ԫ���üĴ���
	RN8302DataComm.ucTempBuf[1] = 0x00; //�����;���ֵ�ۼ� �����Ĵ����ۼ��� ����ʸ���Ͱ������ߵ���
	RN8302DataComm.ucTempBuf[0] = 0x00;
	meter_spi_write(EMUCFG,RN8302DataComm.ucTempBuf,3);

	//4�����У���Ĵ���
		// ��ѹ�����ʼ��
	meter_spi_write(GSUA, (uint8_t*)&zore, 2);
	meter_spi_write(GSUB, (uint8_t*)&zore, 2);
	meter_spi_write(GSUC, (uint8_t*)&zore, 2);
	
	// ���������ʼ��
	meter_spi_write(GSIA, (uint8_t*)&zore, 2);
	meter_spi_write(GSIB, (uint8_t*)&zore, 2);
	meter_spi_write(GSIC, (uint8_t*)&zore, 2);
	//meter_spi_write(GSIN, (u8 *)&rn8302_init_para->para_GSIN, 2);

	// �й���λ��ʼ��
	//meter_spi_write(PA_PHSL, (uint8_t*)&zore, 2);
	//meter_spi_write(PB_PHSL, (uint8_t*)&zore, 2);
	//meter_spi_write(PC_PHSL, (uint8_t*)&zore, 2);

	// �޹���λ��ʼ��
	//meter_spi_write(QA_PHSL, (uint8_t*)&zore, 2);
	//meter_spi_write(QB_PHSL, (uint8_t*)&zore, 2);
	//meter_spi_write(QC_PHSL, (uint8_t*)&zore, 2);

	RN8302DataComm.ucTemp8 = 0xDC; //д����
	meter_spi_write(WREN,RN8302DataComm.ucTempBuf,1);
}

//��ѹ����У��
void meter_voltage_gain_calibrate(void)
{
	StructDataComm_TypeDef RN8302DataComm;
	meter_info_t temp_meter = {0};
	float temp;

	meter_spi_read(UA, (u8 *)&temp_meter.Vrms_a, 4);//ʵ�ʵ�ѹֵΪtemp_meter.Vrms_a/200000
	log_d("reg ua value:%d", temp_meter.Vrms_a);
	meter_spi_read(UB, (u8 *)&temp_meter.Vrms_b, 4);
	log_d("reg ub value:%d", temp_meter.Vrms_b);
	meter_spi_read(UC, (u8 *)&temp_meter.Vrms_c, 4);
	log_d("reg uc value:%d", temp_meter.Vrms_c);

	if(temp_meter.Vrms_a < std_voltage_value){//A���ѹУ��
		temp = (float)(temp_meter.Vrms_a-std_voltage_value)/std_voltage_value;
		rn8302b_calibrate_para.para_GSUA = fabs(temp)/(1+temp)*32768;
	}else
	{
		temp = (float)(temp_meter.Vrms_a-std_voltage_value)/std_voltage_value;
		rn8302b_calibrate_para.para_GSUA = 65536 - temp/(1+temp)*32768;

	}

	if(temp_meter.Vrms_b < std_voltage_value){//B���ѹУ��
		temp = (float)(temp_meter.Vrms_b-std_voltage_value)/std_voltage_value;
		rn8302b_calibrate_para.para_GSUB = fabs(temp)/(1+temp)*32768;
	}else
	{
		temp = (float)(temp_meter.Vrms_b-std_voltage_value)/std_voltage_value;
		rn8302b_calibrate_para.para_GSUB = 65536 - temp/(1+temp)*32768;
	}

	if(temp_meter.Vrms_c < std_voltage_value){//C���ѹУ��
		temp = (float)(temp_meter.Vrms_c-std_voltage_value)/std_voltage_value;
		rn8302b_calibrate_para.para_GSUC = fabs(temp)/(1+temp)*32768;
	}else
	{
		temp = (float)(temp_meter.Vrms_c-std_voltage_value)/std_voltage_value;
		rn8302b_calibrate_para.para_GSUC = 65536 - temp/(1+temp)*32768;
	}

	log_i("USUA reg value :%x", rn8302b_calibrate_para.para_GSUA);
	log_i("USUB reg value :%x", rn8302b_calibrate_para.para_GSUB);
	log_i("USUC reg value :%x", rn8302b_calibrate_para.para_GSUC);

	RN8302DataComm.ucTemp8 = 0xe5; // дʹ��λ
	meter_spi_write(WREN, RN8302DataComm.ucTempBuf, 1);

	meter_spi_write(GSUA, (uint8_t*)&rn8302b_calibrate_para.para_GSUA, 2);
	meter_spi_write(GSUB, (uint8_t*)&rn8302b_calibrate_para.para_GSUB, 2);
	meter_spi_write(GSUC, (uint8_t*)&rn8302b_calibrate_para.para_GSUC, 2);

	RN8302DataComm.ucTemp8 = 0xDC; //д����
	meter_spi_write(WREN, RN8302DataComm.ucTempBuf, 1);
	
}

void meter_current_gain_calibrate(void)
{
	StructDataComm_TypeDef RN8302DataComm;
	meter_info_t temp_meter = {0};
	float temp;

	meter_spi_read(IA, (u8 *)&temp_meter.Irms_a, 4);//ʵ�ʵ���ֵΪtemp_meter.Irms_a/5000000
	log_d("reg Ia value:%d", temp_meter.Irms_a);
	meter_spi_read(IB, (u8 *)&temp_meter.Irms_b, 4);
	log_d("reg Ib value:%d", temp_meter.Irms_b);
	meter_spi_read(IC, (u8 *)&temp_meter.Irms_c, 4);
	log_d("reg Ic value:%d", temp_meter.Irms_c);

	if (temp_meter.Irms_a < std_current_value)//A�����У��
	{
		temp = (float)(temp_meter.Irms_a - std_current_value)/std_current_value;
		rn8302b_calibrate_para.para_GSIA = fabs(temp)/(1+temp)*32768;
	}else
	{
		temp = (float)(temp_meter.Irms_a - std_current_value)/std_current_value;
		rn8302b_calibrate_para.para_GSIA = 65536 - temp/(1+temp)*32768;
	}

	if (temp_meter.Irms_b < std_current_value)//B�����У��
	{
		temp = (float)(temp_meter.Irms_b - std_current_value)/std_current_value;
		rn8302b_calibrate_para.para_GSIB = fabs(temp)/(1+temp)*32768;
	}else
	{
		temp = (float)(temp_meter.Irms_b - std_current_value)/std_current_value;
		rn8302b_calibrate_para.para_GSIB = 65536 - temp/(1+temp)*32768;
	}

	if (temp_meter.Irms_c < std_current_value)//C�����У��
	{
		temp = (float)(temp_meter.Irms_c - std_current_value)/std_current_value;
		rn8302b_calibrate_para.para_GSIC = fabs(temp)/(1+temp)*32768;
	}else
	{
		temp = (float)(temp_meter.Irms_c - std_current_value)/std_current_value;
		rn8302b_calibrate_para.para_GSIC = 65536 - temp/(1+temp)*32768;
	}

	log_i("USIA reg value :%x", rn8302b_calibrate_para.para_GSIA);
	log_i("USIB reg value :%x", rn8302b_calibrate_para.para_GSIB);
	log_i("USIC reg value :%x", rn8302b_calibrate_para.para_GSIC);

	RN8302DataComm.ucTemp8 = 0xe5; // дʹ��λ
	meter_spi_write(WREN, RN8302DataComm.ucTempBuf, 1);

	meter_spi_write(GSIA, (uint8_t*)&rn8302b_calibrate_para.para_GSIA, 2);
	meter_spi_write(GSIB, (uint8_t*)&rn8302b_calibrate_para.para_GSIB, 2);
	meter_spi_write(GSIC, (uint8_t*)&rn8302b_calibrate_para.para_GSIC, 2);

	RN8302DataComm.ucTemp8 = 0xDC; //д����
	meter_spi_write(WREN,RN8302DataComm.ucTempBuf,1);
}



//��λУ��
void meter_phase_calibrate(void)
{
	StructDataComm_TypeDef RN8302DataComm;
	meter_info_t temp_meter = {0};
	float temp;

	meter_spi_read(PA, (u8 *)&temp_meter.Ppwr_a, 4);
	meter_spi_read(PB, (u8 *)&temp_meter.Ppwr_b, 4);
	meter_spi_read(PC, (u8 *)&temp_meter.Ppwr_c, 4);
	temp_meter.Ppwr_a = temp_meter.Ppwr_a/2;


	if(temp_meter.Ppwr_a < std_power_value)//A��
	{
		temp = (float)(temp_meter.Ppwr_a - std_power_value)/std_power_value;
		rn8302b_calibrate_para.para_PA_PHSL = fabs(temp)/1.732*32768;
	}else
	{
		temp = (float)(temp_meter.Ppwr_a - std_power_value)/std_power_value;
		rn8302b_calibrate_para.para_PA_PHSL = 65536 - (temp)/1.732*32768;		
	}
	rn8302b_calibrate_para.para_QA_PHSL = rn8302b_calibrate_para.para_PA_PHSL;

	if(temp_meter.Ppwr_b < std_power_value)//B��
	{
		temp = (float)(temp_meter.Ppwr_b - std_power_value)/std_power_value;
		rn8302b_calibrate_para.para_PB_PHSL = fabs(temp)/1.732*32768;
	}else
	{
		temp = (float)(temp_meter.Ppwr_b - std_power_value)/std_power_value;
		rn8302b_calibrate_para.para_PB_PHSL = 65536 - (temp)/1.732*32768;		
	}
	rn8302b_calibrate_para.para_QB_PHSL = rn8302b_calibrate_para.para_PB_PHSL;

	if(temp_meter.Ppwr_c < std_power_value)//C��
	{
		temp = (float)(temp_meter.Ppwr_c - std_power_value)/std_power_value;
		rn8302b_calibrate_para.para_PC_PHSL = fabs(temp)/1.732*32768;
	}else
	{
		temp = (float)(temp_meter.Ppwr_c - std_power_value)/std_power_value;
		rn8302b_calibrate_para.para_PC_PHSL = 65536 - (temp)/1.732*32768;		
	}
	rn8302b_calibrate_para.para_QC_PHSL = rn8302b_calibrate_para.para_PC_PHSL;

	log_i("USIA reg value :%x", rn8302b_calibrate_para.para_PA_PHSL);
	log_i("USIB reg value :%x", rn8302b_calibrate_para.para_PB_PHSL);
	log_i("USIC reg value :%x", rn8302b_calibrate_para.para_PC_PHSL);
}

//��ȡ����ֵ
int rn8302b_value_read(meter_para_e type, uint32_t *num)
{
	int res = RT_EOK;
	uint32_t  *value  = (uint32_t*)num;
	uint32_t result;
	
	switch(type)
	{
		case CURRENT_PHASE_A:
			result = meter_info.Irms_a;
			log_d(" current_A = %d.%d%d (A)", result/100, result%100/10, result%10);
		break;
		
		case CURRENT_PHASE_B:
			result = meter_info.Irms_b;
			log_d(" current_B = %d.%d%d (A)", result/100, result%100/10, result%10);
		break;
		
		case CURRENT_PHASE_C:
			result = meter_info.Irms_c;
			log_d(" current_C = %d.%d%d (A)", result/100, result%100/10, result%10);
		break;

		case CURRENT_PHASE_TOTAL:
			result = meter_info.Irms_a + meter_info.Irms_b + meter_info.Irms_c;
			if ((result / 100) <= 1){
				result = 0;
			}
			log_d(" current_total = %d.%d%d (A)", result/100, result%100/10, result%10);
		break;
		
		case VOLTAGE_PHASE_A:
			result = meter_info.Vrms_a;
			log_d(" voltage_A = %d.%d%d (V)", result/100, result%100/10, result%10);
		break;
		
		case VOLTAGE_PHASE_B:
			result = meter_info.Vrms_b;
			log_d(" voltage_B = %d.%d%d (V)", result/100, result%100/10, result%10);
		break;
		
		case VOLTAGE_PHASE_C:
			result = meter_info.Vrms_c;
			log_d(" voltage_C = %d.%d%d (V)", result/100, result%100/10, result%10);
		break;
		
		case VOLTAGE_LINE_AB:
			result = meter_info.Vrms_a*1732/1000;
			log_d("channel%d voltage_AB = %d.%d%d (V)", channel, result/100, result%100/10, result%10);
		break;

		case VOLTAGE_LINE_BC:
			result = meter_info.Vrms_b*1732/1000;
			log_d("channel%d voltage_AB = %d.%d%d (V)", channel, result/100, result%100/10, result%10);
		break;

		case VOLTAGE_LINE_CA:
			result = meter_info.Vrms_c*1732/1000;
			log_d("channel%d voltage_AB = %d.%d%d (V)", channel, result/100, result%100/10, result%10);
		break;
		
		case POWER_PHASE_A:
			result = meter_info.Ppwr_a;
			log_d(" power_A = %d.%d%d (W)", result/100, result%100/10, result%10);
		break;
		
		case POWER_PHASE_B:
			result = meter_info.Ppwr_b;
			log_d(" power_B = %d.%d%d (W)", result/100, result%100/10, result%10);
		break;
		
		case POWER_PHASE_C:
			result = meter_info.Ppwr_c;
			log_d(" power_C = %d.%d%d (W)", result/100, result%100/10, result%10);
		break;
		
		case POWER_TOTAL:
			result = meter_info.Ppwr_total;
			log_d(" power_Total = %d.%d%d (W)", result/100, result%100/10, result%10);
		break;
		
		case ENERGY_PHASE_A://���޸�
			result = meter_info.Epa_a_now;
			log_d(" energy_a = %d.%d%d (Kwh)", result/100, result%100/10, result%10);
		break;
		
		case ENERGY_PHASE_B:
			result = meter_info.Epa_b_now;
			log_d(" energy_b = %d.%d%d (Kwh)", result/100, result%100/10, result%10);
		break;
		
		case ENERGY_PHASE_C:
			result = meter_info.Epa_c_now;
			log_d(" energy_c = %d.%d%d (Kwh)", result/100, result%100/10, result%10);
		break;
		
		case ENERGY_TOTAL:
			result = meter_info.Epa_total_now;
			log_d(" energy_total = %d.%d%d (Kwh)", result/100, result%100/10, result%10);
		break;

		case FREQ:
			result = meter_info.freq;
			log_d(" frequent = %d.%d hz", result/10, result%10);
		break;

		default:
		break;
		
	}
		*value = result;
	
	return res;
	
}
/**
 ******************************************************************************
 ** @brief  ��ȡCP�߹��ϱ�־λ
 ** @param	state    : �洢״ָ̬��
 ** @return rt_err_t
 ******************************************************************************/
rt_err_t app_meter_fault_get(void * state)
{
    uint8_t *pt_state = (uint8_t *)state;
    if (pt_state != RT_NULL){
        *pt_state = meter_fault;
    }
   
    return 0;
}

/*������оƬ�Ƿ�ͨ������*/
uint8_t meter_check(void){
	uint8_t result = FALSE;
	uint32_t meter_id = 0;
	if(meter_fault == TRUE)
		return result;
	meter_spi_read(DeviceID, (uint8_t*)&meter_id, 3);
	if(meter_id == 0x830200){
		result = TRUE;
		meter_fault = FALSE;
	}else{
		result = FALSE;
		meter_fault = TRUE;
	}

	return result;
}

/*������������*/
void phase_type_detect(void){
	meter_info_t temp_meter;
	#define VALID_VOLTAGE_MIN 10000/*10V*/
	meter_spi_read(UA, (u8 *)&temp_meter.Vrms_a, 4);//ʵ�ʵ�ѹֵΪtemp_meter.Vrms_a/200000
	meter_spi_read(UB, (u8 *)&temp_meter.Vrms_b, 4);
	meter_spi_read(UC, (u8 *)&temp_meter.Vrms_c, 4);

	temp_meter.Vrms_a =  temp_meter.Vrms_a/VRMS_FARC;
	temp_meter.Vrms_b =  temp_meter.Vrms_b/VRMS_FARC;
	temp_meter.Vrms_c =  temp_meter.Vrms_c/VRMS_FARC;

	log_i("Vrms_a:%d, Vrms_b:%d, Vrms_c:%d", temp_meter.Vrms_a, temp_meter.Vrms_b, temp_meter.Vrms_c);
	if((temp_meter.Vrms_a > VALID_VOLTAGE_MIN)&&(temp_meter.Vrms_b > VALID_VOLTAGE_MIN)&&(temp_meter.Vrms_c > VALID_VOLTAGE_MIN)){
		device_phase_type = THREE_PHASE;
	}else
	if((temp_meter.Vrms_a > VALID_VOLTAGE_MIN)&&(temp_meter.Vrms_b < VALID_VOLTAGE_MIN)&&(temp_meter.Vrms_c < VALID_VOLTAGE_MIN)){
		device_phase_type = SINGLE_PHASE;
	}else{
		device_phase_type = ERROR_PHASE;
	}

	if(device_phase_type != ERROR_PHASE){
		log_i("device phase type is %s", (device_phase_type == SINGLE_PHASE)?"SINGLE PHASE":"THREE PHASE");
	}else{
		log_e("device phase type detect judge failed");
	}
}

phase_type_e get_phase_type(void)
{
	return device_phase_type;
}

uint8_t meter_get_ctclamp_current(uint32_t* value){
	uint32_t temp;
	meter_spi_read(IN, (u8 *)&temp, 4);
	log_d("ct clamp reg: %x", temp);
	temp = temp/(IRMS_FARC*2000);
	log_d("ct clamp out current: %dmA", temp);
	*value = temp;
	return 0;
}

static void app_meter_thread(void *param)
{
	uint32_t meter_id = 0;
    /*meter����SPI��ʼ��*/
	meter_spi_init();
	//relay_init();//������
	log_d("meter soft SPI IO Init.");
	rt_thread_mdelay(500);

	if(meter_check()){
		rn8302_init();
	}

	rt_thread_mdelay(1000);
	phase_type_detect();

	while(1) {

		if(meter_check()){
			meter_data_read(&meter_info);
		}
		//meter_spi_read(DeviceID, (uint8_t*)&meter_id, 3);
		//rt_thread_delay(50);
		rt_thread_delay(250);

	}
}

void dbg_meter_info(){
	uint32_t ua, ia, ub, uc, ib, ic, power, erengy, frq;
	uint32_t ctclamp_value;

	meter_data_read(&meter_info);
	rn8302b_value_read(CURRENT_PHASE_A, &ia);
	log_i(" phase A current value is %d.%d%dA", ia/100, ia%100/10, ia%10);
	rn8302b_value_read(VOLTAGE_PHASE_A, &ua);
	log_i(" phase A voltage value is %d.%d%dV", ua/100, ua%100/10, ua%10);

	if(device_phase_type == THREE_PHASE){
		rn8302b_value_read(CURRENT_PHASE_B, &ib);
		log_i(" phase B current value is %d.%d%dA", ib/100, ib%100/10, ib%10);
		rn8302b_value_read(VOLTAGE_PHASE_B, &ub);
		log_i(" phase B voltage value is %d.%d%dV", ub/100, ub%100/10, ub%10);
		rn8302b_value_read(CURRENT_PHASE_C, &ic);
		log_i(" phase C current value is %d.%d%dA", ic/100, ic%100/10, ic%10);
		rn8302b_value_read(VOLTAGE_PHASE_C, &uc);
		log_i(" phase C voltage value is %d.%d%dV", uc/100, uc%100/10, uc%10);
	}

	rn8302b_value_read(POWER_TOTAL, &power);
	log_i(" total power a value is %d.%d%d(KW)", power/1000, power/100%10, power/10%10);
	rn8302b_value_read(ENERGY_TOTAL, &erengy);
	log_i("  total energy is %d(wh)", erengy);
	rn8302b_value_read(FREQ, &frq);
	log_i(" frequent value is %d(hz)", frq);

	meter_get_ctclamp_current(&ctclamp_value);
	log_i("ctclamp  value is %dmA.", ctclamp_value);

}

rt_err_t app_meter_init(void)
{
	rt_thread_t thread = RT_NULL;
    
	thread = rt_thread_create("meter", app_meter_thread, RT_NULL,
                               1024,
                               16,
                               10);
	if (thread == RT_NULL){
		log_e("meter thread init error");
		return -RT_ERROR;
	}
	rt_thread_startup(thread);
	
	return RT_EOK;
}

#ifdef RT_USING_FINSH
static int meter(int argc, char **argv)
{
    int result = RT_EOK;
	
	if (argc != 2){
		rt_kprintf("Usage: \n");
    	rt_kprintf("meter function[init/GSU/GSI/read/open/close]\n");
		rt_kprintf("eg meter init.\n");
		rt_kprintf("   when standard voltage has been set.\n");
		rt_kprintf("   meter GSU.\n");
		rt_kprintf("\n");
		return -RT_ERROR;
	} 

	if (!(strcmp(argv[1], "init"))){
		meter_calibrate_init();
		rt_kprintf("meter calibrate init");
	}else
	if (!(strcmp(argv[1], "GSU"))){
		meter_voltage_gain_calibrate();
		rt_kprintf("meter voltage gain calibrate");
	}else
	if (!(strcmp(argv[1], "GSI"))){
		meter_current_gain_calibrate();
		rt_kprintf("meter current gain calibrate");
	}else
	if(!(strcmp(argv[1], "read"))){
		dbg_meter_info();
	}else
	if(!(strcmp(argv[1], "open"))){
		relay_control(OPEN);
	}else	
	if(!(strcmp(argv[1], "close"))){
		relay_control(CLOSE);
	}else
	{
		rt_kprintf("meter function[init/GSU/GSI/read/open/close]\n");
	}
		
	return result;
}

MSH_CMD_EXPORT(meter, meter function);

#endif /* RT_USING_FINSH */

#endif





